### Project 13 5 in 1 Muilti-functional Car (Line Tracking, Obstacle Avoidance, Bluetooth and IR Remote Control, Distance Detecting) ![](media/wps33.png) **1.Introduction** In this project, we will put five functions (namely line tracking, obstacle avoidance, Bluetooth and IR remote control, distance detection) together into one to realize the working mode of the car. Press the button “5” of IR remote control to start line tracking; button “6” to start ultrasonic obstacle avoidance and distance detecting; button “7” to start IR remote control, button “8”to start Bluetooth remote control, and press reset button to enter initialized mode. **2.Schematic Diagram** ![](media/wps34.png) **3.Connection Diagram** ![](media/wps35.png) **4.Sample Code** ```c #include //including libraries of I2C-LCD1602 liquid crystal #include //including libraries of I2C #include //including libraries of remote control #define RECV_PIN 12 //pin 12 of IR remoter control receiver IRrecv irrecv(RECV_PIN); //defining pin 12 of IR remoter control decode_results results; //cache of decode of IR remoter control #define IR_Go 0x00ff629d //going forward #define IR_Back 0x00ffa857 //going backward #define IR_Left 0x00ff22dd //turning left #define IR_Right 0x00ffc23d //turning right #define IR_Stop 0x00ff02fd //stop #define IR_Servo_L 0x00ff6897 //motor turning left #define IR_Servo_R 0x00ff9867 //motor turning right #define IR_Speed_UP 0x00ffb04f //increasing speed #define IR_Speed_DOWN 0x00ff30cf //decreasing speed #define IR_XunJi_Mode 0x00ff18e7 #define IR_Self_Control 0x00ff7a85 //ultrasonic distance detecting #define IR_IR_Control 0x00ff10ef #define IR_Bluetooth_Control 0x00ff38c7 #define IR_ESC 0x00ff52ad //quitting from remote control ////////////////////////////////////////////////// #define SensorLeft 6 //sensor left pin of line tracking module #define SensorMiddle 9 //sensor middle pin of line tracking module #define SensorRight 11 //sensor right pin of line tracking module unsigned char SL; //state of left sensor of line tracking module unsigned char SM; //state of middle sensor of line tracking module unsigned char SR; //state of right sensor of line tracking module int inputPin=A0; // ultrasonic module ECHO to A0 int outputPin=A1; // ultrasonic module TRIG to A1 unsigned char Bluetooth_val; // ultrasonic module TRIG to A1 LiquidCrystal_I2C lcd(0x27,16,2); //defining liquid crystal #define Lpwm_pin 5 //pin of controlling speed---- ENA of motor driver board #define Rpwm_pin 10 //pin of controlling speed---- ENB of motor driver board int pinLB=2; //pin of controlling turning---- IN1 of motor driver board int pinLF=4; //pin of controlling turning---- IN2 of motor driver board int pinRB=7; //pin of controlling turning---- IN3 of motor driver board int pinRF=8; //pin of controlling turning---- IN4 of motor driver board unsigned char Lpwm_val = 250; //initialized left wheel speed at 250 unsigned char Rpwm_val = 250; //initialized right wheel speed at 250 int Car_state=0; //the working state of car int servopin=3; //defining digital port pin 3, connecting to signal line of servo motor int myangle; //defining variable of angle int pulsewidth; //defining variable of pulse width unsigned char DuoJiao=60; //initialized angle of motor at 60° void Sensor_IO_Config() //IO initialized function of three line tracking , all setting at input { pinMode(SensorLeft,INPUT); pinMode(SensorMiddle,INPUT); pinMode(SensorRight,INPUT); } void Sensor_Scan(void) //function of reading-in signal of line tracking module { SL = digitalRead(SensorLeft); SM = digitalRead(SensorMiddle); SR = digitalRead(SensorRight); } void servopulse(int servopin,int myangle) //defining a function of pulse { pulsewidth=(myangle*11)+500; //converting angle into pulse width value at 500-2480 digitalWrite(servopin,HIGH); //increasing the level of motor interface to upmost delayMicroseconds(pulsewidth); //delaying microsecond of pulse width value digitalWrite(servopin,LOW); //decreasing the level of motor interface to the least delay(20-pulsewidth/1000); } void Set_servopulse(int set_val) { for(int i=0;i<=10;i++) //giving motor enough time to turn to assigning point servopulse(servopin,set_val); //invokimg pulse function } void M_Control_IO_config(void) { pinMode(pinLB,OUTPUT); // /pin 2 pinMode(pinLF,OUTPUT); // pin 4 pinMode(pinRB,OUTPUT); // pin 7 pinMode(pinRF,OUTPUT); // pin 8 pinMode(Lpwm_pin,OUTPUT); // pin 11 (PWM) pinMode(Rpwm_pin,OUTPUT); // pin10(PWM) } void Set_Speed(unsigned char Left,unsigned char Right) //function of setting speed { analogWrite(Lpwm_pin,Left); analogWrite(Rpwm_pin,Right); } void advance() // going forward { digitalWrite(pinRB,LOW); // making motor move towards right rear digitalWrite(pinRF,HIGH); digitalWrite(pinLB,LOW); // making motor move towards left rear digitalWrite(pinLF,HIGH); Car_state = 1; show_state(); } void turnR() //turning right(dual wheel) { digitalWrite(pinRB,LOW); //making motor move towards right rear digitalWrite(pinRF,HIGH); digitalWrite(pinLB,HIGH); digitalWrite(pinLF,LOW); //making motor move towards left front Car_state = 4; show_state(); } void turnL() //turning left(dual wheel) { digitalWrite(pinRB,HIGH); digitalWrite(pinRF,LOW ); //making motor move towards right front digitalWrite(pinLB,LOW); //making motor move towards left rear digitalWrite(pinLF,HIGH); Car_state = 3; show_state(); } void stopp() //stop { digitalWrite(pinRB,HIGH); digitalWrite(pinRF,HIGH); digitalWrite(pinLB,HIGH); digitalWrite(pinLF,HIGH); Car_state = 5; show_state(); } void back() //back up { digitalWrite(pinRB,HIGH); //making motor move towards right rear digitalWrite(pinRF,LOW); digitalWrite(pinLB,HIGH); //making motor move towards left rear digitalWrite(pinLF,LOW); Car_state = 2; show_state() ; } void show_state(void) { lcd.setCursor(0, 1); switch(Car_state) { case 1:lcd.print(" Go ");Serial.print(" \r\n GO"); break; case 2:lcd.print("Back ");Serial.print(" \r\n Back"); break; case 3:lcd.print("Left ");Serial.print(" \r\n Left"); break; case 4:lcd.print("Right");Serial.print(" \r\n Right"); break; case 5:lcd.print("Stop ");Serial.print(" \r\n Stop"); break; default: break; } } void LCD1602_init(void) //including initialized function of liquid crystal { lcd.init(); //invoking initialized function of LCD in LiquidCrystal_I2C.h delay(10); //delaying for 10 millisecond lcd.backlight(); //open backlight of LCD1602 lcd.clear(); //clear screen } void Show_V(unsigned char V) { lcd.setCursor(11, 0); lcd.print("V= "); lcd.setCursor(13, 0); lcd.print(V,DEC); Serial.print("\n Speed = "); Serial.print(V,DEC); } void Show_DuoJiao(unsigned char Jiao) { lcd.setCursor(6,1); lcd.print("C= "); lcd.setCursor(8, 1); lcd.print(Jiao,DEC); Serial.print("\n JiaoDu = "); Serial.print(Jiao,DEC); } void Xunji_Mode(void) //function of line tracking { lcd.setCursor(0, 0); //setting cursor in the first row and column lcd.print("Xunji_Mode "); Sensor_Scan(); if (SM == HIGH)// middle sensor in black area { if (SL == LOW & SR == HIGH) // black on left, white on right, turn left { turnR(); } else if (SR == LOW & SL == HIGH) // white on left, black on right, turn right { turnL(); } else // white on both sides, going forward { advance(); } } else // middle sensor on white area { if (SL== LOW & SR == HIGH)// black on left, white on right, turn left { turnR(); } else if (SR == LOW & SL == HIGH) // white on left, black on right, turn right { turnL(); } else // all white, stop { back(); delay(100); stopp() ; } } } void Self_Control(void)//self-going, ultrasonic obstacle avoidance { int H; lcd.setCursor(0, 0); //setting cursor in the first row and column lcd.print("Self_Ctr "); Show_V(Lpwm_val); Set_servopulse(DuoJiao); Show_DuoJiao(DuoJiao); H = Ultrasonic_Ranging(1); delay(300); if(Ultrasonic_Ranging(1) < 35) { stopp(); delay(100); back(); delay(50); } if(Ultrasonic_Ranging(1) < 60) { stopp(); delay(100); Set_servopulse(5); Show_DuoJiao(5); int L = ask_pin_L(2); delay(300); Set_servopulse(177); Show_DuoJiao(177); int R = ask_pin_R(3); delay(300); if(ask_pin_L(2) > ask_pin_R(3)) { back(); delay(100); turnL(); delay(400); stopp(); delay(50); Set_servopulse(DuoJiao); Show_DuoJiao(DuoJiao); H = Ultrasonic_Ranging(1); delay(500); } if(ask_pin_L(2) <= ask_pin_R(3)) { back(); delay(100); turnR(); delay(400); stopp(); delay(50); Set_servopulse(DuoJiao); Show_DuoJiao(DuoJiao); H = Ultrasonic_Ranging(1); delay(300); } if (ask_pin_L(2) < 35 && ask_pin_R(3)< 35) { stopp(); delay(50); back(); delay(50); } } else { advance(); } } int Ultrasonic_Ranging(unsigned char Mode)//function of ultrasonic distance detecting ,MODE=1,displaying,no displaying under other situation { int old_distance; digitalWrite(outputPin, LOW); delayMicroseconds(2); digitalWrite(outputPin, HIGH); delayMicroseconds(10); digitalWrite(outputPin, LOW); int distance = pulseIn(inputPin, HIGH); // reading the duration of high level distance= distance/58; // Transform pulse time to distance if(Mode==1) { lcd.setCursor(11, 1); lcd.print("H= "); lcd.setCursor(13, 1); lcd.print(distance,DEC); Serial.print("\n H = "); Serial.print(distance,DEC); return distance; } else return distance; } int ask_pin_L(unsigned char Mode) { int old_Ldistance; digitalWrite(outputPin, LOW); delayMicroseconds(2); digitalWrite(outputPin, HIGH); delayMicroseconds(10); digitalWrite(outputPin, LOW); int Ldistance = pulseIn(inputPin, HIGH); Ldistance= Ldistance/58; // Transform pulse time to distance if(Mode==2) { lcd.setCursor(11, 1); lcd.print("L= "); lcd.setCursor(13, 1); lcd.print(Ldistance,DEC); Serial.print("\n L = "); Serial.print(Ldistance,DEC); return Ldistance; } else return Ldistance; } int ask_pin_R(unsigned char Mode) { int old_Rdistance; digitalWrite(outputPin, LOW); delayMicroseconds(2); digitalWrite(outputPin, HIGH); // delayMicroseconds(10); digitalWrite(outputPin, LOW); int Rdistance = pulseIn(inputPin, HIGH); Rdistance= Rdistance/58; // Transform pulse time to distance if(Mode==3) { lcd.setCursor(11, 1); lcd.print("R= "); lcd.setCursor(13, 1); lcd.print(Rdistance,DEC); Serial.print("\n R = "); Serial.print(Rdistance,DEC); return Rdistance; } else return Rdistance; } void IR_Control(void) //remote control,when pressing“#”,it quitting from the mode { unsigned long Key; lcd.setCursor(0,0); //setting cursor in the first row and column lcd.print("IR_Ctr "); while(Key!=IR_ESC) { if(irrecv.decode(&results)) //to judge whether serial port receive data { Key = results.value; switch(Key) { case IR_Go:advance(); //UP break; case IR_Back: back(); //back break; case IR_Left:turnL(); //Left break; case IR_Right:turnR(); //Righ break; case IR_Stop:stopp(); //stop break; case IR_Servo_L: if(DuoJiao<=180)//motor turning left { DuoJiao+=10; Set_servopulse(DuoJiao); Show_DuoJiao(DuoJiao); } break; case IR_Servo_R: if(DuoJiao-10>=0)//motor turning right { DuoJiao-=10; Set_servopulse(DuoJiao); Show_DuoJiao(DuoJiao); } break; case IR_Speed_UP:if(Rpwm_val+10<=250&&Rpwm_val+10<=250)//increasing speed { Lpwm_val+=10; Rpwm_val+=10; Set_Speed(Lpwm_val,Rpwm_val); Show_V(Lpwm_val); } break; case IR_Speed_DOWN:if(Rpwm_val-10>=0&&Rpwm_val-10>=0)//decreasing speed { Lpwm_val-=10; Rpwm_val-=10; Set_Speed(Lpwm_val,Rpwm_val); Show_V(Lpwm_val); } break; default: break; } irrecv.resume(); // Receive the next value } } lcd.clear(); lcd.setCursor(0, 0); //setting cursor in the first row and column lcd.print(" Wait Signal "); stopp(); } void Bluetooth_Control() //Bluetooth remote control { lcd.setCursor(0, 0); //setting cursor in the first row and column lcd.print("BluetoothControl"); if(Serial.available()) //to judge whether serial port receive data { Bluetooth_val=Serial.read(); //reading value of Bluetooth serial port, giving the value to val switch(Bluetooth_val) { case 'U':advance(); //UP break; case 'D': back(); //back break; case 'L':turnL(); //Left break; case 'R':turnR(); //Right break; case 'S':stopp(); //stop break; } } } void setup() { pinMode(servopin,OUTPUT); //setting motor interface as output LCD1602_init(); //initializing 1602 M_Control_IO_config(); //motor controlling the initialization of IO Set_Speed(Lpwm_val,Rpwm_val); //setting initialized speed Set_servopulse(DuoJiao); //setting initialized motor angle Sensor_IO_Config(); //initializing IO of line tracking module irrecv.enableIRIn(); //starting receiving IR remote control signal pinMode(inputPin, INPUT); //starting receiving IR remote control signal pinMode(outputPin, OUTPUT); //IO of ultrasonic module Serial.begin(9600); //initialized serial port , using Bluetooth as serial port, setting baud lcd.setCursor(0, 0); //setting cursor at 0.0 lcd.print(" Wait Signal "); //LCD printing character string stopp(); //stop } void loop() { if (irrecv.decode(&results)) {//when receiving a button if(results.value == IR_XunJi_Mode) { while(IR_XunJi_Mode) { Xunji_Mode(); } //pressing “OK” on remote controller, and entering remote control mode } if(results.value == IR_Self_Control) { while(IR_Self_Control) { Self_Control(); //pressing “OK” on remote controller, and entering remote control mode } } if(results.value == IR_IR_Control) { while(IR_IR_Control) { IR_Control(); //pressing “OK” on remote controller, and entering remote control mode } } if(results.value == IR_Bluetooth_Control) { while(IR_Bluetooth_Control) { Bluetooth_Control(); //pressing “OK” on remote controller, and entering remote control mode } } irrecv.resume(); // Receive the next value } delay(10); } ``` **5.Result** The car is controlled by IR remote control and mobile phone Bluetooth together. After connection, press number 5 key of IR remote control, and the car enter into line tracking mode to go along with black line. When press reset, and then press number 6 key, the car enter into ultrasonic obstacle avoidance mode and it goes with automatic obstacle avoidance, displaying current condition and distance between car and obstacle on LCD. Press reset and then number 7 key, the car is in IR control, its motion is controlled by IR up, down, right and left key, “OK” means stop. Number 1 and 2 key control rotation of motor, while 3 and 4 key control move speed. Reset again, the car goes into Bluetooth mode. If connecting to Bluetooth APP, you can control the motion of the car by APP.